package com.wtao.imagereader;

import android.app.Activity;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.io.IOException;

/**
 * 某些车机可能用不了camera1的api方法，得用新版的camera2的api方法
 * （也有些平板和手机camera1和camera2的都可以用）
 */
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback, Camera.PreviewCallback, View.OnClickListener {
    String TAG = "CameraActivity";
    /*private static final int SRC_FRAME_WIDTH = 640;
    private static final int SRC_FRAME_HEIGHT = 480;*/
    private static int SRC_FRAME_WIDTH = 1920;
    private static int SRC_FRAME_HEIGHT = 1080;
    //private static final int IMAGE_FORMAT = ImageFormat.YV12;
    private static final int IMAGE_FORMAT = ImageFormat.NV21;
    int index = 0;
    private Camera mCamera;
    private Camera.Parameters mParams;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    //private int cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    private int cameraId = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        if (getIntent() != null) {
            String cameraIdStr = getIntent().getStringExtra("dmsCameraID");
            if (TextUtils.isEmpty(cameraIdStr)) {
                cameraIdStr = "2";
            }
            Log.e(TAG, "getIntent() != null cameraIdStr=" + cameraIdStr);
            cameraId = Integer.parseInt(cameraIdStr);

            String widthStr = getIntent().getStringExtra("width");
            if (TextUtils.isEmpty(widthStr)) {
                widthStr = "1920";
            }
            SRC_FRAME_WIDTH = Integer.parseInt(widthStr);

            String heightStr = getIntent().getStringExtra("height");
            if (TextUtils.isEmpty(heightStr)) {
                heightStr = "1080";
            }
            SRC_FRAME_HEIGHT = Integer.parseInt(heightStr);
        } else {
            cameraId = 2;
            SRC_FRAME_WIDTH = 1920;
            SRC_FRAME_HEIGHT = 1080;
        }
        initView();
        setListener();
    }

    private void initView() {
        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.setFixedSize(SRC_FRAME_WIDTH, SRC_FRAME_HEIGHT);
        mSurfaceHolder.addCallback(this);
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        findViewById(R.id.bt_back).setOnClickListener(v->{
            finish();
        });
    }

    private void setListener() {
        // set Listener if you want, eg: onClickListener
    }

    @Override
    public void onClick(View v) {
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        //ImageUtils.saveImageData(data, "Image_" + index + ".jpg");
        index++;
        camera.addCallbackBuffer(data);
    }

    private void openCamera(SurfaceHolder holder) {
        releaseCamera(); // release Camera, if not release camera before call camera, it will be locked
        try {
            mCamera = Camera.open(cameraId);
            mParams = mCamera.getParameters();
            setCameraDisplayOrientation(this, cameraId, mCamera);
            mParams.setPreviewSize(SRC_FRAME_WIDTH, SRC_FRAME_HEIGHT);
            mParams.setPreviewFormat(IMAGE_FORMAT); // setting preview format：YV12
            mCamera.setParameters(mParams); // setting camera parameters
            try {
                mCamera.setPreviewDisplay(holder);
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }

            mCamera.setPreviewCallback(this);
            mCamera.startPreview();
        } catch (Exception e) {
            e.printStackTrace();
            if (e.getMessage().contains("Unknown camera ID")) {
                Toast.makeText(this, "无摄像头id为" + cameraId + "的摄像头", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private synchronized void releaseCamera() {
        if (mCamera != null) {
            try {
                mCamera.setPreviewCallback(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                mCamera.stopPreview();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                mCamera.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
            mCamera = null;
        }
    }

    /**
     * Android API: Display Orientation Setting
     * Just change screen display orientation,
     * the rawFrame data never be changed.
     */
    private void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int displayDegree;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            displayDegree = (info.orientation + degrees) % 360;
            displayDegree = (360 - displayDegree) % 360;  // compensate the mirror
        } else {
            displayDegree = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(displayDegree);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        openCamera(holder); // open camera
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseCamera();
    }
}